package finalfinancialanalyst.business;

import java.util.Map;
import java.util.Date;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.util.SortOrder;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;

public class AccountList implements Serializable {
    
        private static final long serialVersionUID = 1L;
 
	private ArrayList<Account> accounts;
        private static AccountList instance;
	 
	private AccountList() {
            accounts = new ArrayList<Account>(); 
	}
        
        public static AccountList getInstance() {
            if (instance == null) {
                
                //Try to load from file
                instance = (AccountList)IO.loadFromFile(IO.getAccountsFile());
                if (instance == null) {
                   instance = new AccountList(); 
                   
                   //TODO default data
                   instance.addAccount(new Account("My Cash", CurrencyList.getInstance().retrieveCurrencyBySymbol("EUR"), BigDecimal.TEN, "Cash"));
                   instance.addAccount(new Account("AIB", CurrencyList.getInstance().retrieveCurrencyBySymbol("EUR"), BigDecimal.valueOf(Double.parseDouble("1500")), "Bank"));
                   instance.addAccount(new Account("Ulster Bank", CurrencyList.getInstance().retrieveCurrencyBySymbol("EUR"), BigDecimal.valueOf(Double.parseDouble("764")), "Bank"));
                }
            }
            return instance;
        }
	 
	public ArrayList getList() {
		return accounts;
	}
	 
	public boolean addAccount(Account acc) {
		return (accounts.add(acc));
	}
	 
	public boolean deleteAccount(Account acc) {
                return (accounts.remove(acc));
	}
	 
	public Account retrieveAccount(String name) {
		for (Account acc : accounts) {
                    if (acc.getName().equalsIgnoreCase(name)) {
                        return acc;
                    }
                }
                return null;
	}
        
        public int size() {
            return accounts.size();
        }
        
        public Account get(int index) {
            return accounts.get(index);
        }
        
        public PieDataset getCategoryExpenditureStats(Date dateStart, Date dateEnd, Currency curr) {
           DefaultPieDataset dataset = new DefaultPieDataset();
            
           for (Account acc : accounts) {
               PieDataset accdata = acc.getCategoryExpenditureStats(dateStart, dateEnd, curr);
               
               List<Comparable> keys = accdata.getKeys();
               for (Comparable key : keys) {
                  Number amount = accdata.getValue(key);
                  
                  if (dataset.getIndex(key) != -1) {
                      amount = amount.doubleValue() + dataset.getValue(key).doubleValue();
                  }
                  dataset.setValue(key, amount);
               }
            }
            dataset.sortByValues(SortOrder.DESCENDING);
            return dataset;
        }
        
        public Money getBalance(Date toDate, Currency curr){
            BigDecimal balance = BigDecimal.ZERO;
            for (Account acc : accounts) {
                balance = balance.add(acc.getBalance(toDate).convertTo(curr).getAmount());
            }
            return new Money(balance.toString(),curr);
        }
        
        public Money getBalance(Currency curr) {
            return getBalance(null,curr);
        }
	 
	 
	/**
	 * Returns statistics for the accounts contained. All parameters are optional and ignored if not specified
	 * 
	 * Data are returned in format "Description - number" so they can be shown both in a table or in a graph
	 */
	public Map getStats(String category, Date dateStart, Date dateEnd) {
		return null;
	}

    public TimeSeriesCollection getBalanceStats(Date dateStart, Date dateEnd, Currency selectedCurrency) {
            TimeSeriesCollection dataset = new TimeSeriesCollection();
            TimeSeries series = new TimeSeries("All accounts", Day.class);
            Date curDate = dateStart;
            while(curDate.before(dateEnd)) {
            
                series.add(new Day(curDate), getBalance(curDate,selectedCurrency).getAmount());
                
                //increment
                Calendar cal = Calendar.getInstance();
                cal.setTime(curDate);
                cal.add(Calendar.DAY_OF_MONTH, 1);
                curDate = cal.getTime();
            }
            dataset.addSeries(series);
            
            for (Account acc: accounts) {
                TimeSeriesCollection col = acc.getBalanceStats(dateStart, dateEnd, selectedCurrency);
                List list = col.getSeries();
                for (Object o : list) {
                    dataset.addSeries((TimeSeries)o);
                }
            }
            
            return dataset;
    }
	 
}
 
